<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue + Cesium 原生时间轴播放</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="/Cesium/Cesium.js"></script>
    <link href="/Cesium/Widgets/widgets.css" rel="stylesheet">
    <style>
        body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
        #app { width: 100%; height: 100vh; position: relative; }
        #cesiumContainer { width: 100%; height: 100vh; }
        .info {
            position: absolute; top: 10px; left: 10px; z-index: 1000;
            background: rgba(0,0,0,0.8); color: #fff; padding: 14px; border-radius: 6px; max-width: 560px;
        }
        .row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
        .row button { background: #4CAF50; color: #fff; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; }
        .row button:hover { background: #45a049; }
        .row button.danger { background: #e84c3d; }
        .row button.danger:hover { background: #cf3e30; }
        .row button:disabled { background: #666; cursor: not-allowed; }
        .row select, .row input { padding: 4px 6px; font-size: 12px; }
        .kv { font-size: 12px; line-height: 1.6; }
        .kv b { color: #ffd666; }
        .timeline { display:flex; align-items:center; gap:8px; margin-top:6px; }
        .timeline input[type="range"] { width: 240px; }
        
        /* 右侧表格样式 */
        .geojson-table {
            position: absolute; top: 10px; right: 10px; z-index: 1000;
            background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px;
            width: 400px; max-height: 80vh; overflow-y: auto;
        }
        .geojson-table h3 { margin: 0 0 12px 0; color: #ffd666; font-size: 14px; }
        .geojson-table table { width: 100%; border-collapse: collapse; font-size: 11px; }
        .geojson-table th, .geojson-table td { 
            padding: 6px 8px; text-align: left; border-bottom: 1px solid #333; 
        }
        .geojson-table th { background: rgba(255,255,255,0.1); font-weight: bold; }
        .geojson-table tr:hover { background: rgba(255,255,255,0.05); }
        .geojson-table .actions { display: flex; gap: 4px; }
        .geojson-table .actions button { 
            padding: 2px 6px; font-size: 10px; background: #2196F3; 
            border: none; color: white; border-radius: 3px; cursor: pointer; 
        }
        .geojson-table .actions button:hover { background: #1976D2; }
        .geojson-table .actions button.danger { background: #f44336; }
        .geojson-table .actions button.danger:hover { background: #d32f2f; }
        .geojson-table .json-preview { 
            max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; 
        }
    </style>
</head>
<body>
<div id="app">
    <div id="cesiumContainer"></div>
    <div class="info">
        <div class="kv">状态：<b>{{ status }}</b></div>
        <div class="row">
            <label>时间轴模式
                <select v-model="timeMode" @change="applyTimeMode">
                    <option value="utc-now">方案A：实时UTC（起点=现在）</option>
                    <option value="relative-fixed">方案B：相对秒（固定起点并缩放Timeline）</option>
                </select>
            </label>
            <button @click="play">开始</button>
            <button @click="pause" :disabled="!playing">暂停</button>
            <button @click="reset">重置</button>
            <button @click="nudge(-5)">快退5s</button>
            <button @click="nudge(5)">快进5s</button>
            <label>倍速
                <select v-model.number="speed" @change="applySpeed">
                    <option :value="-4">-4x</option>
                    <option :value="-2">-2x</option>
                    <option :value="-1">-1x</option>
                    <option :value="0.5">0.5x</option>
                    <option :value="1">1x</option>
                    <option :value="2">2x</option>
                    <option :value="4">4x</option>
                </select>
            </label>
        </div>
        <div class="row timeline">
            <span>{{ currentSec.toFixed(1) }}s</span>
            <input type="range"
                   :min="0"
                   :max="endSeconds"
                   step="0.1"
                   :value="currentSec"
                   @input="onSliderInput"
                   @change="onSliderChange"
                   @mousedown="isSeeking=true" @mouseup="isSeeking=false" @mouseleave="isSeeking=false"
                   @touchstart="isSeeking=true" @touchend="isSeeking=false">
            <span>{{ endSeconds }}s</span>
        </div>
        <div class="row">
            <button @click="startDrawPolygon" :disabled="drawing">开始绘制多边形</button>
            <button @click="finishDrawPolygon" :disabled="!drawing">完成</button>
            <button @click="clearDrawPolygon" class="danger">清空多边形</button>
            <span style="font-size:12px;color:#ccc">提示：左键落点、移动预览、再次左键继续、点击“完成”闭合。</span>
        </div>
        <div class="row">
            <button @click="startRealTimeTrack" :disabled="realTimeMode">开始实时轨迹</button>
            <button @click="stopRealTimeTrack" :disabled="!realTimeMode">停止实时轨迹</button>
            <button @click="resetRealTimeTrack">重置轨迹</button>
            <span style="font-size:12px;color:#ccc">实时轨迹：每秒添加一个点</span>
        </div>
        <div class="kv">当前位置：<b>{{ posText }}</b></div>
        <div class="kv">当前区段：<b>{{ segText }}</b></div>
        <div class="kv" v-if="polygonGeoJSON">
            <div style="margin-top: 8px;">
                <strong style="color: #ffd666;">多边形GeoJSON：</strong>
                <button @click="copyGeoJSON" style="margin-left: 8px; background: #2196F3; color: white; border: none; padding: 2px 6px; border-radius: 3px; font-size: 10px; cursor: pointer;">复制</button>
            </div>
            <pre style="background: rgba(0,0,0,0.3); padding: 8px; border-radius: 4px; font-size: 10px; max-height: 120px; overflow-y: auto; margin-top: 4px; white-space: pre-wrap; word-break: break-all;">{{ polygonGeoJSON }}</pre>
        </div>
    </div>
    
    <!-- 右侧GeoJSON记录表格 -->
    <div class="geojson-table">
        <h3>GeoJSON记录 ({{ geojsonRecords.length }})</h3>
        <table v-if="geojsonRecords.length > 0">
            <thead>
                <tr>
                    <th>序号</th>
                    <th>时间</th>
                    <th>点数</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(record, index) in geojsonRecords" :key="index">
                    <td>{{ index + 1 }}</td>
                    <td>{{ formatTime(record.timestamp) }}</td>
                    <td>{{ record.pointCount }}</td>
                    <td class="actions">
                        <button @click="copyRecordGeoJSON(index)" title="复制GeoJSON">复制</button>
                        <button @click="viewRecordGeoJSON(index)" title="查看完整GeoJSON">查看</button>
                        <button @click="deleteRecord(index)" class="danger" title="删除记录">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>
        <div v-else style="text-align: center; color: #999; padding: 20px;">
            暂无绘制记录
        </div>
    </div>
</div>

<script>
const { createApp } = Vue;
createApp({
    data() {
        return {
            status: '正在初始化...',
            viewer: null,
            entity: null,
            trackEntity: null,
            positionProp: null,
            start: null,
            end: null,
            playing: false,
            speed: 1,
            currentSec: 0,
            endSeconds: 0,
            posText: '-',
            segText: '-',
            timeMode: 'utc-now',
            isSeeking: false,
            // 绘制相关
            drawing: false,
            drawPositions: [], // Cartesian3
            drawPolygonEntity: null,
            drawOutlineEntity: null,
            drawHandler: null,
            polygonGeoJSON: null, // 存储多边形的GeoJSON
            geojsonRecords: [], // 存储所有GeoJSON记录
            flightPath: [
                { longitude: 116.4074, latitude: 39.9042, altitude: 10000, name: '北京', timestamp: 0 }
            ],
            // 实时轨迹相关
            realTimeMode: false,
            realTimeInterval: null,
            currentRealTimeIndex: 0,
            realTimePoints: [
                { longitude: 116.8,    latitude: 38.5,    altitude: 12000, name: '河北', timestamp: 1 },
                { longitude: 117.2,    latitude: 37.0,    altitude: 11000, name: '山东', timestamp: 2 },
                { longitude: 117.8,    latitude: 35.5,    altitude: 13000, name: '江苏', timestamp: 3 },
                { longitude: 118.5,    latitude: 34.0,    altitude: 12000, name: '安徽', timestamp: 4 },
                { longitude: 119.2,    latitude: 32.5,    altitude: 11000, name: '江苏', timestamp: 5 },
                { longitude: 120.0,    latitude: 31.0,    altitude: 10000, name: '上海', timestamp: 6 },
                { longitude: 121.4737, latitude: 31.2304, altitude: 8000,  name: '上海虹桥', timestamp: 7 }
            ]
        };
    },
    computed: { clock() { return this.viewer ? this.viewer.clock : null; } },
    mounted() { this.initCesium(); },
    methods: {
        // 安全缩放
        safeZoomTo(target) {
            try {
                const res = this.viewer.zoomTo(target);
                if (res && typeof res.then === 'function') {
                    res.catch(() => {
                        this.viewer.camera.setView({
                            destination: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 2000000),
                            orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO, roll: 0.0 }
                        });
                    });
                }
            } catch (_) {
                this.viewer.camera.setView({
                    destination: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 2000000),
                    orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO, roll: 0.0 }
                });
            }
        },
        focusFirstPoint() {
            if (!this.flightPath || this.flightPath.length === 0) return;
            const p0 = this.flightPath[0];
            const height = Math.max(30000, (p0.altitude || 0) + 80000);
            this.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromDegrees(p0.longitude, p0.latitude, height),
                orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO + 0.2, roll: 0.0 }
            });
        },
        initCesium() {
            try {
                this.viewer = new Cesium.Viewer('cesiumContainer', {
                    terrain: Cesium.Terrain.fromWorldTerrain(),
                    animation: true, timeline: true,
                    baseLayerPicker: true, geocoder: true, homeButton: true,
                    sceneModePicker: true, navigationHelpButton: true,
                    fullscreenButton: true, infoBox: true, selectionIndicator: true
                });
                this.viewer.scene.globe.depthTestAgainstTerrain = false;
                this.endSeconds = this.flightPath[this.flightPath.length - 1].timestamp;
                this.applyTimeMode();

                // 初始状态只显示第一个点，不显示轨迹线
                this.focusFirstPoint();

                this.clock.onTick.addEventListener(this.onTick);
                this.status = '已就绪：使用顶部按钮或底部 Animation/Timeline 控件';
            } catch (e) { this.status = '初始化失败'; console.error(e); }
        },
        applyTimeMode() {
            if (this.timeMode === 'relative-fixed') {
                this.start = Cesium.JulianDate.fromDate(new Date(Date.UTC(2025, 7, 28, 0, 0, 0)));
            } else {
                this.start = Cesium.JulianDate.now();
            }
            this.end = Cesium.JulianDate.addSeconds(this.start, this.endSeconds, new Cesium.JulianDate());
            this.clock.startTime = this.start.clone();
            this.clock.stopTime = this.end.clone();
            this.clock.currentTime = this.start.clone();
            this.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
            this.clock.multiplier = this.speed;
            this.clock.shouldAnimate = false;

            if (this.entity) this.viewer.entities.remove(this.entity);
            this.positionProp = new Cesium.SampledPositionProperty();
            for (const p of this.flightPath) {
                const t = Cesium.JulianDate.addSeconds(this.start, p.timestamp, new Cesium.JulianDate());
                const pos = Cesium.Cartesian3.fromDegrees(p.longitude, p.latitude, p.altitude);
                this.positionProp.addSample(t, pos);
            }
            this.entity = this.viewer.entities.add({
                availability: new Cesium.TimeIntervalCollection([
                    new Cesium.TimeInterval({ start: this.start, stop: this.end })
                ]),
                position: this.positionProp,
                orientation: new Cesium.VelocityOrientationProperty(this.positionProp),
                point: { pixelSize: 20, color: Cesium.Color.BLUE, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 },
                label: { text: '模拟飞机', font: '14pt sans-serif', style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2,
                         verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -40),
                         fillColor: Cesium.Color.WHITE, outlineColor: Cesium.Color.BLACK }
            });

            if (this.timeMode === 'relative-fixed') {
                this.viewer.timeline.zoomTo(this.start, this.end);
            }
        },
        onTick() {
            if (this.isSeeking) return;
            const secs = Math.max(0, Math.min(this.endSeconds, Cesium.JulianDate.secondsDifference(this.clock.currentTime, this.start)));
            this.currentSec = Math.round(secs * 10) / 10;
            let idx = 0;
            for (let i = 0; i < this.flightPath.length - 1; i++) {
                const a = this.flightPath[i].timestamp, b = this.flightPath[i + 1].timestamp;
                if (secs >= a && secs <= b) { idx = i; break; }
            }
            const A = this.flightPath[idx], B = this.flightPath[Math.min(idx + 1, this.flightPath.length - 1)];
            const span = Math.max(1e-6, B.timestamp - A.timestamp);
            const segProg = Math.min(1, Math.max(0, (secs - A.timestamp) / span));
            const lon = A.longitude + (B.longitude - A.longitude) * segProg;
            const lat = A.latitude + (B.latitude - A.latitude) * segProg;
            this.posText = `${lon.toFixed(2)}, ${lat.toFixed(2)}`;
            this.segText = `${A.name}(${A.timestamp}s) → ${B.name}(${B.timestamp}s)`;
        },
        play() {
            this.clock.shouldAnimate = false;
            this.clock.currentTime = this.start.clone();
            this.currentSec = 0;
            this.playing = true;
            this.clock.shouldAnimate = true;
            this.status = '播放中（从头开始）';
            this.focusFirstPoint();
        },
        pause() { this.clock.shouldAnimate = false; this.playing = false; this.status = '已暂停'; },
        reset() { this.pause(); this.clock.currentTime = this.start.clone(); this.safeZoomTo(this.trackEntity); this.status = '已重置到起点'; },
        applySpeed() { this.clock.multiplier = this.speed; },
        nudge(delta) {
            let t = Cesium.JulianDate.addSeconds(this.clock.currentTime, delta, new Cesium.JulianDate());
            if (Cesium.JulianDate.lessThan(t, this.start)) t = this.start.clone();
            if (Cesium.JulianDate.greaterThan(t, this.end)) t = this.end.clone();
            this.clock.currentTime = t;
        },
        onSliderInput(evt) {
            this.isSeeking = true;
            const sec = Math.max(0, Math.min(this.endSeconds, Number(evt.target.value)));
            this.currentSec = Math.round(sec * 10) / 10;
        },
        onSliderChange(evt) {
            const sec = Math.max(0, Math.min(this.endSeconds, Number(evt.target.value)));
            const clamped = Math.round(sec * 10) / 10;
            this.clock.currentTime = Cesium.JulianDate.addSeconds(this.start, clamped, new Cesium.JulianDate());
            this.isSeeking = false;
        },
        // ================= 多边形绘制 =================
        startDrawPolygon() {
            if (this.drawing) return;
            this.drawing = true;
            this.drawPositions = [];
            if (this.drawPolygonEntity) { this.viewer.entities.remove(this.drawPolygonEntity); this.drawPolygonEntity = null; }
            if (this.drawOutlineEntity) { this.viewer.entities.remove(this.drawOutlineEntity); this.drawOutlineEntity = null; }
            if (this.drawHandler) { this.drawHandler.destroy(); this.drawHandler = null; }
            this.drawHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas);

            // 左键点击：落点
            this.drawHandler.setInputAction((movement) => {
                const cart = this.getCartesianFromMouse(movement.position);
                if (!cart) return;
                this.drawPositions.push(cart);
                this.ensureDynamicPolygon();
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            // 右键点击：完成绘制
            this.drawHandler.setInputAction((movement) => {
                if (this.drawing && this.drawPositions.length >= 3) {
                    this.finishDrawPolygon();
                }
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

            // 移动：动态预览末点
            this.drawHandler.setInputAction((movement) => {
                if (!this.drawing || this.drawPositions.length === 0) return;
                const cart = this.getCartesianFromMouse(movement.endPosition);
                if (!cart) return;
                const temp = this.drawPositions.slice();
                temp.push(cart);
                this.updateDynamicPolygon(temp);
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        },
        finishDrawPolygon() {
            if (!this.drawing) return;
            this.drawing = false;
            if (this.drawHandler) { this.drawHandler.destroy(); this.drawHandler = null; }
            // 最终以 drawPositions 生成实体
            if (this.drawPositions.length < 3) return;
            this.updateDynamicPolygon(this.drawPositions, true);
        },
        clearDrawPolygon() {
            this.drawing = false;
            this.drawPositions = [];
            this.polygonGeoJSON = null; // 清除GeoJSON
            
            // 清除所有记录及其对应的实体
            for (const record of this.geojsonRecords) {
                if (record.polygonEntity) {
                    this.viewer.entities.remove(record.polygonEntity);
                }
                if (record.outlineEntity) {
                    this.viewer.entities.remove(record.outlineEntity);
                }
            }
            this.geojsonRecords = []; // 清空记录数组
            
            if (this.drawHandler) { this.drawHandler.destroy(); this.drawHandler = null; }
            if (this.drawPolygonEntity) { this.viewer.entities.remove(this.drawPolygonEntity); this.drawPolygonEntity = null; }
            if (this.drawOutlineEntity) { this.viewer.entities.remove(this.drawOutlineEntity); this.drawOutlineEntity = null; }
        },
        getCartesianFromMouse(winPos) {
            if (!winPos) return null;
            const scene = this.viewer.scene;
            let cartesian = null;
            if (scene.pickPositionSupported) {
                cartesian = scene.pickPosition(winPos);
            }
            if (!Cesium.defined(cartesian)) {
                const ray = this.viewer.camera.getPickRay(winPos);
                cartesian = scene.globe.pick(ray, scene);
            }
            return cartesian || null;
        },
        ensureDynamicPolygon() {
            if (this.drawPolygonEntity) return;
            const hierarchyCb = new Cesium.CallbackProperty(() => {
                const list = (this._previewPositions || this.drawPositions);
                if (!list || list.length < 3) return null;
                return new Cesium.PolygonHierarchy(list);
            }, false);
            this.drawPolygonEntity = this.viewer.entities.add({
                polygon: {
                    hierarchy: hierarchyCb,
                    material: Cesium.Color.fromBytes(255, 165, 0, 100), // 橙色半透明
                    perPositionHeight: true,
                    outline: false
                }
            });
            this.drawOutlineEntity = this.viewer.entities.add({
                polyline: {
                    positions: new Cesium.CallbackProperty(() => {
                        const list = (this._previewPositions || this.drawPositions);
                        if (!list || list.length < 2) return [];
                        return list.concat(list[0]); // 闭合预览
                    }, false),
                    width: 2,
                    material: Cesium.Color.ORANGE
                }
            });
        },
        updateDynamicPolygon(positions, finalize = false) {
            this._previewPositions = positions;
            if (finalize) {
                // 清除预览实体
                if (this.drawPolygonEntity) { this.viewer.entities.remove(this.drawPolygonEntity); this.drawPolygonEntity = null; }
                if (this.drawOutlineEntity) { this.viewer.entities.remove(this.drawOutlineEntity); this.drawOutlineEntity = null; }
                this._previewPositions = null;
                
                // 生成GeoJSON（会自动创建实体并添加到记录中）
                this.generateGeoJSON(positions);
            }
        },
        
        // 生成GeoJSON
        generateGeoJSON(positions) {
            if (!positions || positions.length < 3) {
                this.polygonGeoJSON = null;
                return;
            }
            
            // 将Cartesian3坐标转换为经纬度
            const coordinates = [];
            for (const pos of positions) {
                const cartographic = Cesium.Cartographic.fromCartesian(pos);
                const longitude = Cesium.Math.toDegrees(cartographic.longitude);
                const latitude = Cesium.Math.toDegrees(cartographic.latitude);
                coordinates.push([longitude, latitude]);
            }
            
            // 闭合多边形（首尾相连）
            if (coordinates.length > 0) {
                coordinates.push(coordinates[0]);
            }
            
            const geojson = {
                type: "Feature",
                properties: {
                    name: "绘制多边形",
                    timestamp: new Date().toISOString()
                },
                geometry: {
                    type: "Polygon",
                    coordinates: [coordinates]
                }
            };
            
            this.polygonGeoJSON = JSON.stringify(geojson, null, 2);
            
            // 添加到记录表格
            this.geojsonRecords.push({
                timestamp: new Date(),
                pointCount: positions.length,
                geojson: geojson,
                geojsonString: this.polygonGeoJSON,
                polygonEntity: null, // 将在下面设置
                outlineEntity: null  // 将在下面设置
            });
            
            // 获取刚添加的记录索引
            const recordIndex = this.geojsonRecords.length - 1;
            
            // 创建多边形实体并保存引用
            const polygonEntity = this.viewer.entities.add({
                polygon: {
                    hierarchy: new Cesium.PolygonHierarchy(positions),
                    material: Cesium.Color.fromBytes(255, 165, 0, 100),
                    perPositionHeight: true
                }
            });
            
            const outlineEntity = this.viewer.entities.add({
                polyline: {
                    positions: positions.concat(positions[0]),
                    width: 2,
                    material: Cesium.Color.ORANGE
                }
            });
            
            // 保存实体引用到记录中
            this.geojsonRecords[recordIndex].polygonEntity = polygonEntity;
            this.geojsonRecords[recordIndex].outlineEntity = outlineEntity;
        },
        
        // 复制GeoJSON到剪贴板
        copyGeoJSON() {
            if (!this.polygonGeoJSON) return;
            
            navigator.clipboard.writeText(this.polygonGeoJSON).then(() => {
                // 临时显示复制成功提示
                const btn = event.target;
                const originalText = btn.textContent;
                btn.textContent = '已复制';
                btn.style.background = '#4CAF50';
                setTimeout(() => {
                    btn.textContent = originalText;
                    btn.style.background = '#2196F3';
                }, 1000);
            }).catch(err => {
                console.error('复制失败:', err);
                // 降级方案：使用传统方法
                const textArea = document.createElement('textarea');
                textArea.value = this.polygonGeoJSON;
                document.body.appendChild(textArea);
                textArea.select();
                document.execCommand('copy');
                document.body.removeChild(textArea);
                
                const btn = event.target;
                const originalText = btn.textContent;
                btn.textContent = '已复制';
                btn.style.background = '#4CAF50';
                setTimeout(() => {
                    btn.textContent = originalText;
                    btn.style.background = '#2196F3';
                }, 1000);
            });
        },
        
        // 格式化时间显示
        formatTime(date) {
            if (!date) return '-';
            const d = new Date(date);
            return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}:${d.getSeconds().toString().padStart(2, '0')}`;
        },
        
        // 复制记录中的GeoJSON
        copyRecordGeoJSON(index) {
            const record = this.geojsonRecords[index];
            if (!record) return;
            
            navigator.clipboard.writeText(record.geojsonString).then(() => {
                // 临时显示复制成功提示
                const btn = event.target;
                const originalText = btn.textContent;
                btn.textContent = '已复制';
                btn.style.background = '#4CAF50';
                setTimeout(() => {
                    btn.textContent = originalText;
                    btn.style.background = '#2196F3';
                }, 1000);
            }).catch(err => {
                console.error('复制失败:', err);
                // 降级方案
                const textArea = document.createElement('textarea');
                textArea.value = record.geojsonString;
                document.body.appendChild(textArea);
                textArea.select();
                document.execCommand('copy');
                document.body.removeChild(textArea);
                
                const btn = event.target;
                const originalText = btn.textContent;
                btn.textContent = '已复制';
                btn.style.background = '#4CAF50';
                setTimeout(() => {
                    btn.textContent = originalText;
                    btn.style.background = '#2196F3';
                }, 1000);
            });
        },
        
        // 查看记录中的完整GeoJSON
        viewRecordGeoJSON(index) {
            const record = this.geojsonRecords[index];
            if (!record) return;
            
            // 显示在弹窗中
            alert(`GeoJSON记录 ${index + 1}:\n\n${record.geojsonString}`);
        },
        
        // 删除记录
        deleteRecord(index) {
            if (confirm(`确定要删除第 ${index + 1} 条记录吗？`)) {
                const record = this.geojsonRecords[index];
                if (record) {
                    // 删除对应的多边形实体
                    if (record.polygonEntity) {
                        this.viewer.entities.remove(record.polygonEntity);
                    }
                    if (record.outlineEntity) {
                        this.viewer.entities.remove(record.outlineEntity);
                    }
                }
                // 从数组中删除记录
                this.geojsonRecords.splice(index, 1);
            }
        },
        
        // ================= 实时轨迹功能 =================
        startRealTimeTrack() {
            if (this.realTimeMode) return;
            
            this.realTimeMode = true;
            this.currentRealTimeIndex = 0;
            
            // 重置轨迹线
            this.updateRealTimeTrack();
            
            // 每秒添加一个点
            this.realTimeInterval = setInterval(() => {
                if (this.currentRealTimeIndex < this.realTimePoints.length) {
                    this.addRealTimePoint();
                } else {
                    this.stopRealTimeTrack();
                }
            }, 1000);
            
            this.status = '实时轨迹：每秒添加一个点';
        },
        
        stopRealTimeTrack() {
            this.realTimeMode = false;
            if (this.realTimeInterval) {
                clearInterval(this.realTimeInterval);
                this.realTimeInterval = null;
            }
            this.status = '实时轨迹已停止';
        },
        
        resetRealTimeTrack() {
            this.stopRealTimeTrack();
            this.currentRealTimeIndex = 0;
            
            // 重置flightPath到初始状态（只有第一个点）
            this.flightPath = [
                { longitude: 116.4074, latitude: 39.9042, altitude: 10000, name: '北京', timestamp: 0 }
            ];
            
            // 重新创建轨迹线和飞机实体
            this.updateRealTimeTrack();
            this.applyTimeMode();
            
            this.status = '轨迹已重置到初始状态';
        },
        
        addRealTimePoint() {
            if (this.currentRealTimeIndex >= this.realTimePoints.length) return;
            
            const newPoint = this.realTimePoints[this.currentRealTimeIndex];
            this.flightPath.push(newPoint);
            this.currentRealTimeIndex++;
            
            // 更新轨迹线
            this.updateRealTimeTrack();
            
            // 更新时间轴
            this.endSeconds = this.flightPath[this.flightPath.length - 1].timestamp;
            this.applyTimeMode();
            
            // 自动聚焦到最新点
            this.focusLatestPoint();
        },
        
        updateRealTimeTrack() {
            // 移除旧的轨迹线
            if (this.trackEntity) {
                this.viewer.entities.remove(this.trackEntity);
            }
            
            // 创建新的轨迹线
            const flat = [];
            for (const p of this.flightPath) {
                flat.push(p.longitude, p.latitude, p.altitude);
            }
            
            if (flat.length >= 6) { // 至少需要2个点（6个坐标值）
                this.trackEntity = this.viewer.entities.add({
                    polyline: {
                        positions: Cesium.Cartesian3.fromDegreesArrayHeights(flat),
                        width: 5,
                        material: Cesium.Color.YELLOW.withAlpha(1.0),
                        clampToGround: false
                    }
                });
            }
        },
        
        focusLatestPoint() {
            if (this.flightPath.length === 0) return;
            
            const latestPoint = this.flightPath[this.flightPath.length - 1];
            const height = Math.max(30000, (latestPoint.altitude || 0) + 80000);
            
            this.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromDegrees(latestPoint.longitude, latestPoint.latitude, height),
                orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO + 0.2, roll: 0.0 }
            });
        }
    }
}).mount('#app');
</script>
</body>
</html>
    